/**
 * Created by ange on 2016/4/25.
 */
(function ($) {

    /**
     * 定义一个RGB类
     * @param r
     * @param g
     * @param b
     */
    var mRGB = function (r, g, b) {
        this.r = r;
        this.g = g;
        this.b = b;
    };

    /**
     * 从"rgb(0, 70, 255)"获得RGB的值
     * @param rgbString
     * @returns {mRGB}
     */
    function getRGB(rgbString) {
        var parts = rgbString.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
        // parts now should be ["rgb(0, 70, 255)", "0", "70", "255"]
        delete (parts[0]);
        var myrgb = new mRGB;
        myrgb.r = parseInt(parts[1]);
        myrgb.g = parseInt(parts[2]);
        myrgb.b = parseInt(parts[3]);
        return myrgb;
    }

    /**
     * 将"rgb(0, 70, 255)"转化为 "0070ff"
     * @param rgbString
     */
    function hex2rgb(rgbString) {
        var rgbString = "rgb(0, 70, 255)"; // get this in whatever way.
        var parts = rgbString.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
        // parts now should be ["rgb(0, 70, 255)", "0", "70", "255"]
        delete (parts[0]);
        for (var i = 1; i <= 3; i++) {
            parts[i] = parseInt(parts[i]).toString(16);
            if (parts[i].length == 1) parts[i] = '0' + parts[i];
        }
        var hexString = parts.join(''); // "0070ff"
    }

    /**
     * 对字符进行格式化
     * @returns {*}
     */
    var format = function () {
        if (arguments.length == 0)
            return null;
        var str = arguments[0];
        for (var i = 1; i < arguments.length; i++) {
            var re = new RegExp('\\{' + (i - 1) + '\\}', 'gm');
            str = str.replace(re, arguments[i]);
        }
        return str;
    };

    /**
     * 检查密码强度
     * @param strToCheck 检测的密码字符串
     * @returns {number} 密码强度
     */
    function checkPassword(strToCheck) {
        var len = strToCheck.length;
        if (len == 0) return 1;
        //检测到中文
        var cat = /.*[\u4e00-\u9fa5]+.*$/;
        if (cat.test(strToCheck)) {
            return 1;
        }
        //检测数字
        cat = /\d/;
        var maths = cat.test(strToCheck);
        //检测小写字母
        cat = /[a-z]/;
        var smalls = cat.test(strToCheck);
        //检测大写字母
        cat = /[A-Z]/;
        var bigs = cat.test(strToCheck);
        //检测非单词字符
        cat = /[\W]+/;
        var corps = cat.test(strToCheck);
        //统计
        var num = maths + smalls + bigs + corps;
        //输出强度
        if (len < 6) {
            return 1;
        }
        if (len >= 6 && len <= 8) {
            if (num == 1) return 1;
            if (num == 2 || num == 3) return 2;
            if (num == 4) return 3;
        }
        if (len > 8 && len <= 11) {
            if (num == 1) return 2;
            if (num == 2) return 3;
            if (num == 3) return 4;
            if (num == 4) return 5;
        }
        if (len > 11) {
            if (num == 1) return 3;
            if (num == 2) return 4;
            if (num > 2) return 5;
        }
    }

    /**
     * 两种颜色之间生成插值的数组
     * @param colorA 开始颜色
     * @param colorB 结束颜色
     * @param total 总共分段
     * @returns {Array} 返回的颜色数组
     */
    function color_gradient(colorA, colorB, total) {
        var color_array = [];
        var start = getRGB(colorA);
        var end = getRGB(colorB);
        var kr = Math.round((end.r - start.r) / total);
        var kg = Math.round((end.g - start.g) / total);
        var kb = Math.round((end.b - start.b) / total);

        for (var i = 0; i < total; i++) {
            if (i == 0) {
                color_array[i] = start;
            } else if (i == total - 1) {
                color_array[i] = end;
            } else {
                var r = start.r + i * kr;
                var g = start.g + i * kg;
                var b = start.b + i * kb;
                color_array[i] = new mRGB(r, g, b);
            }
        }
        return color_array;
    }

    /**
     * 主要的控件类
     * @param opts
     */
    var main = function (opts) {
        this.color_start = opts.color_start;//开始颜色
        this.color_end = opts.color_end;//最终颜色
        this.total = opts.total;//总共分段
        this.color_normal = opts.color_normal;//默认颜色
        this.line_class = opts.line_class;//线条class
        //线的颜色数组
        this.color_array = color_gradient(this.color_start, this.color_end, this.total);
        //记录当前密码的强度
        this.strength = 1;
    };

    /**
     * 控件类的方法
     * @type {{createLine: main.createLine, init: main.addHistory, updateView: main.updateView, updateVariable: main.updateVariable}}
     */
    main.prototype = {
        /**
         * 创建线的容器
         */
        createLine: function (container) {
            //线的容器
            var line_container = $("<div></div>").appendTo(container);
            //循环创建
            for (var i = 0; i < this.total; i++) {
                var line = format("<div class='" + this.line_class + "' star='" + (i + 1) + "'></div>");
                line_container.append($(line));
            }
            //中文提示
            var tip = $("<span style='color:#bc0001'>弱</span>").appendTo(line_container);

            this.line_container = line_container;
            this.tip = tip;
        },
        /**
         * 初始化
         * @param $this 使用插件的jq对象
         */
        showlist: function ($this) {
            //控件元素初始化
            var container = $("<div></div>").append("<p style='float: left;margin: 0'>安全系数</p>");
            var line_container = this.createLine(container);
            $this.after(container);//在input后插入container
            //控件元素初始化完毕
            this.container = container;
        },
        /**
         * 更新显示强度的条
         * @param strength 密码强度值，在1-5之间
         */
        updateView: function (strength) {
            var tip = this.tip;
            var color_array = this.color_array;
            var color_normal = this.color_normal;
            var total = this.total;
            //记录当前密码的强度
            this.strength = strength;
            //遍历每个line
            this.line_container.find("div." + this.line_class).each(function () {
                var $this = $(this);//封装jq对象
                var index = $this.attr("star");//序号1,2,3,4,5……到total
                if (index <= strength) {
                    var bacolor = format("rgb({0},{1},{2})", color_array[index - 1].r, color_array[index - 1].g, color_array[index - 1].b);
                    $this.css("background-color", bacolor);
                } else {
                    $this.css("background-color", color_normal);
                }
            });
            //更新tip
            if (strength <= Math.round(total / 5)) {
                tip.html("弱");
            } else if (strength <= Math.round(total * 4 / 5)) {
                tip.html("中");
            } else {
                tip.html("安全");
            }
        },
        updateVariable: function (opts) {
            if (opts.color_normal)this.total = opts.color_normal;//默认颜色
            if (opts.line_class)this.total = opts.line_class;//线条class

            if (opts.color_start || opts.color_end || opts.total) {
                if (opts.color_start) {
                    this.color_start = opts.color_start;
                }//开始颜色
                if (opts.color_end)this.color_end = opts.color_end;//最终颜色
                if (opts.total) {
                    //总共字段有变的情况下，还需要重新绘制控件
                    this.total = opts.total;
                    this.line_container.remove();
                    this.createLine(this.container);
                }
                //颜色，总共字段任一有变都重新计数颜色插值数组
                this.color_array = color_gradient(this.color_start, this.color_end, this.total);
            }
            //更新一下view
            this.updateView(this.strength);
        }
    };

    var methods = {
        showlist: function (settings) {
            var opts = $.extend({}, $.fn.defaults, settings); //使用jQuery.extend 覆盖插件默认参数
            return this.each(function () {

                var self = this;//该元素本身
                var $this = $(self);//JQ对象

                var total = opts.total;//总共分段

                var mainer = new main(opts);
                mainer.addHistory($this);

                //绑定插件的数据
                $this.data("pwdDetect", mainer);

                //绑定函数
                $this.keyup(function () {
                    //获取密码强度
                    var strength = checkPassword($this.val());
                    //strength在1-5之间，映射到total
                    strength = Math.round((strength / 5) * total);
                    //更新操作
                    mainer.updateView(strength);
                });

                //一开始先设置强度为1
                mainer.updateView(1);
            });
        },
        settings: function (settings) {
            //这里的this是一个jq对象
            var mainer = this.data('pwdDetect');
            mainer.updateVariable(settings);
        }
    };

    $.fn.pwdDetect = function () {
        //arguments[0]是传进来的第一个参数
        var method = arguments[0];

        if (methods[method]) {
            method = methods[method];
            arguments = Array.prototype.slice.call(arguments, 1);
        } else if (typeof(method) == 'object' || !method) {
            method = methods.showlist;
        } else {
            $.error('方法 ' + method + ' 并不存在于插件中！');
            return this;
        }

        //调用method方法，用this和arguments,这个this是调用这个插件的dom元素的jq对象
        return method.apply(this, arguments);
    };

    $.fn.defaults = {
        //开始颜色
        color_start: "rgb(255,0,0)",
        //最终颜色
        color_end: "rgb(73,197,25)",
        //总共分段
        total: 5,
        //默认颜色
        color_normal: "rgb(231,231,231)",
        //线条class
        line_class: ""
    };
})(jQuery);
